#include"newtoninterpolation.h"
#include"polymerization.h"
#include<iostream>
#include<cmath>
using std::cin;
using std::cout;
using std::endl;

datanode::datanode()
{
    m_x=m_numberorder=0;
    m_y=NULL;
    m_next=NULL;
}

void datanode::init()
{
    m_y=new double [m_numberorder];
}

datanode::datanode(datanode &temp)
{
    m_x=temp.getx();
    m_numberorder=temp.getnumberorder();
    m_y=new double [m_numberorder];
    for(int i=0;i<m_numberorder;i++)
    {
        *(m_y+i)=temp.getdata(i);
    }
}

datanode::~datanode()
{
    delete [] m_y;

}
datanode * datanode::getnext()  const
{
    return m_next;
}

void datanode::setnext(datanode* next)
{
    m_next=next;
}

void datanode::setdivideddifferent(double difference,int order)
{
    if(order>m_numberorder-1)
    {
        cout<<"bad divideddifference order"<<endl;
        return;
    }
    *(m_y+order)=difference;

}

double datanode::getdata(int order)const
{
    if(order>m_numberorder-1)
    {
        cout<<"bad divideddifference order"<<endl;
        return .0;
    }
    return *(m_y+order);
}


void datanode::sety(double y)
{
    if(m_y)
    *m_y=y;
}



void datanode::setnumberorder(int order)
{
    m_numberorder=order;
}
int datanode::getnumberorder() const
{
    return m_numberorder;
}

void datanode::setx(double x)
{
    m_x=x;
}
double datanode::getx() const
{
    return m_x;
}
void datanode::show() const
{
    double *temp=m_y;
    cout.width(2);
    cout<<m_x<<":  ";
    for(int i=0;i<m_numberorder;i++)
    {
        cout.width(2);
        cout<<*temp<<"  ";
        temp++;
    }
    cout<<endl;
}

//////////////////////////////////////
//data table
//////////////////////////////////////

datatalbe::datatalbe()
{
    m_count=0;
    m_data=NULL;
}

datatalbe::~datatalbe()
{
    datanode * temp;
    while(m_data)
    {
        temp=m_data->getnext();
        delete m_data;
        m_data=temp;
        if(temp)
        {
            temp=temp->getnext();
        }
    }
}

void datatalbe::addnumber(int x,int y)
{

    datanode * temp=new datanode;
    m_count++;
    temp->setx(x);
    temp->setnumberorder(m_count);
    temp->init();
    temp->sety(y);     //sety() must behind init(),before proform init(),m_y don't have space to store value
    if(m_count!=1)
    {
      datanode * prenode=m_data;
      for(int i=1;i<m_count-1;i++)
      {
          prenode=prenode->getnext();
      }
      prenode->setnext(temp);
    }
    else
    {
       m_data=temp;
    }
    temp=NULL;
}

void datatalbe::produce()//make divided difference table
{
    datanode * temp=m_data->getnext();
    datanode * last=m_data;
    for(int i=1;i<m_count;i++)
    {
        for(int j=1;j<temp->getnumberorder();j++)
        {
           temp->setdivideddifferent((temp->getdata(j-1)-last->getdata(j-1))/(this->getx(i+1)-this->getx(i-j+1)),j);
        }
        temp=temp->getnext();
        last=last->getnext();
    }
}

double datatalbe::getx(int n)const
{
    datanode * temp=m_data;
    for(int i=1;i<n;i++)
    {
        temp=temp->getnext();
    }
    return temp->getx();
}

double datatalbe::getdata(int xth,int n)const  //when n is 0 return f(x), when n is 1 return first divided difference
{
    datanode * temp=m_data;
    for(int i=1;i<xth;i++)
    {
        temp=temp->getnext();
    }
    return temp->getdata(n);
}

int datatalbe::getcount()const
{
    return m_count;
}

void datatalbe::show()
{
    datanode * temp=m_data;
    for(int i=0;i<m_count;i++)
    {
        temp->show();
        temp=temp->getnext();
        cout<<endl;
    }
}
